package container

import (
	"codejy/globalfunc"
	"codejy/store"
	"codejy/structdef"
	"codejy/typedefault"
	"codejy/utils"
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

type TypeMap struct {
	Addr        string
	ThreadStore *structdef.ThreadStore
	Map         map[string]string
	NextNames   []string
	NextIndex   int
}

// 创建实例

func (a *TypeMap) CreateTypeDefault(addr string, threadStore *structdef.ThreadStore, parameter ...string) {
	mapv := &TypeMap{
		Addr:        addr,
		ThreadStore: threadStore,
		Map:         make(map[string]string),
		NextNames:   []string{},
		NextIndex:   0,
	}
	store.AddTypeDefaultInstanceStore(threadStore, a.GetTypeName(), addr, mapv)
}

func (a *TypeMap) GetData() interface{} {
	return a.Map
}

func (a *TypeMap) ToStr() string {
	//如果是Map,那么打印出来
	value1, b1 := typedefault.GetTypeDefaultValue[map[string]string](a.ThreadStore, a.GetTypeName(), a.Addr)
	if b1 {
		return a.GetTypeName() + ":" + utils.JsonToMapStr(value1)
	}
	return ""
}

func (a *TypeMap) ParameterProcessing(parameter []string) []string {
	//排除前后""
	for i := range parameter {
		s := parameter[i]
		if strings.HasPrefix(s, "\"") && strings.HasSuffix(s, "\"") {
			s = s[1 : len(s)-1]
			parameter[i] = s
		}
	}
	return parameter
}

// 添加数据
func (a *TypeMap) AddMap(key, value string) {
	//判断key是字符串
	if reflect.TypeOf(key).Kind() != reflect.String {
		panic("Map的key必须是字符串")
	}
	a.Map[key] = value
}

// 通过key删除数据
func (a *TypeMap) DeleteMap(key string) {
	delete(a.Map, key)
}

// 通过key获取数据
func (a *TypeMap) GetMap(key string) string {
	if _, ok := a.Map[key]; !ok {
		return ""
	}
	keyv := a.Map[key]
	return keyv
}

// 获取数量
func (a *TypeMap) GetMapCount() string {

	count := len(a.Map)
	return strconv.Itoa(count)
}

// 获取所有key ,返回值为list实例地址
func (a *TypeMap) GetMapKeys() string {

	var keys []string
	for k := range a.Map {
		keys = append(keys, k)
	}
	return SliceToList(keys, a.ThreadStore)
}

// 获取所有value ,返回值为list实例地址
func (a *TypeMap) GetMapValues() string {

	var values []string
	for _, v := range a.Map {
		values = append(values, v)
	}
	return SliceToList(values, a.ThreadStore)
}

// 判断key是否存在
func (a *TypeMap) IsExistKey(key string) string {

	if _, ok := a.Map[key]; !ok {
		return "false"
	}
	return "true"
}

// 复制map(浅拷贝)
func (a *TypeMap) CopyMap() string {
	newMap := make(map[string]string)
	for k, v := range a.Map {
		newMap[k] = v
	}
	return MapToMap(newMap, a.ThreadStore)
}

// 合并map,如果key相同则后面的会覆盖前面的,返回新Map
func (a *TypeMap) MergeMap(map2 string) string {
	typeDefault := globalfunc.ExecuteFunc("GetTypeDefaultInstanceStore", a.GetTypeName(), map2).(structdef.TypeDefault)
	maps := typeDefault.GetData().(map[string]string)
	newMap := make(map[string]string)
	for k, v := range maps {
		newMap[k] = v
	}
	for k, v := range a.Map {
		newMap[k] = v
	}
	return MapToMap(newMap, a.ThreadStore)
}

// Next
func (a *TypeMap) Next() string {
	if a.NextNames == nil || len(a.NextNames) == 0 {
		//将map的key放入到NextNames中
		for k := range a.Map {
			a.NextNames = append(a.NextNames, k)
		}
	}
	if a.NextIndex >= len(a.NextNames) {
		a.NextNames = nil
		a.NextIndex = 0
		return ""
	}
	name := a.NextNames[a.NextIndex]
	sprintf := fmt.Sprintf("%s,%s", name, a.Map[name])
	a.NextIndex++
	return sprintf
}

func (a *TypeMap) GetDef() string {
	return `
		@CodeManual(def="new("Map")",des="创建Map容器")
		type  Map{
			
			def init{
				core&CreateTypeDefault()
			}

			@CodeManual(def="add($1,$2)",des="添加数据,map.add("key","value")")
			def add{
				core&AddMap($1,$2)  
			}

			@CodeManual(def="del($1)",des="通过key删除数据,map.del("key")")
			def del{
				core&DeleteMap($1)
			}

			@CodeManual(def="get($1)",des="通过key获取数据,map.get("key")")
			def get{
				to core&GetMap($1)
			}

			@CodeManual(def="size()",des="获取数量,map.size()")
			def size{
				to core&GetMapCount()
			}

			@CodeManual(def="keys()",des="获取所有key返回值为list实例地址,map.keys()")
			def keys{
				to core&GetMapKeys()
			}

			@CodeManual(def="values()",des="获取所有value返回值为list实例地址,map.values()")
			def values{
				to core&GetMapValues()
			}

			@CodeManual(def="isExistKey($1)",des="判断key是否存在,map.isExistKey("key")")
			def isExistKey{
				to core&IsExistKey($1)
			}
			//这个是浅拷贝,如果存储的是实例,那么复制的就是实例的地址而不是实例本身数据
			//也就是说,如果修改复制的实例,那么原来的实例也会被修改
			@CodeManual(def="copy()",des="复制自己返回新Map(浅拷贝),map.copy()")
			def copy{
				to core&CopyMap()
			}				
			@CodeManual(def="merge($1)",des="合并其他map返回新的map,map1.merge(map2)")
			def merge{
				to core&MergeMap($1)
			}	

			def toStr{
				to core&ToStr()
			}
			def next{
				to core&Next()
			}

		}
	`
}

func init() {
	typedefault.RegisterTypeDefault(&TypeMap{})
	globalfunc.RegisterFuncAll("MapToMap", MapToMap)
}

func (a *TypeMap) GetTypeName() string {
	return "Map"
}

// 将go语言的map转换为Map实例
func MapToMap(map1 map[string]string, threadStore *structdef.ThreadStore) string {
	addr := typedefault.TypeDefaultNewInstance("Map", threadStore)
	newMap1 := &TypeMap{
		Addr:        addr,
		ThreadStore: threadStore,
		Map:         map1}
	store.AddTypeDefaultInstanceStore(threadStore, "Map", addr, newMap1)
	return addr
}
